﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Data.SqlClient;
using System.Data;
using TSL_Tools.SqlTools;
using ReportingEngine;
using System.IO;
using Xceed.Wpf.Toolkit.PropertyGrid;
using System.ComponentModel;
using System.Xml;
using System.Xml.Serialization;
using VSLT_Reporting.Dialog_Boxes;

namespace VSLT_Reporting
{
    /*---------------------------------------------------------------------------------------------------
     * When adding a value to the app.config file or to the User Settings for this project, please be sure
     * to also add the info here. Choose the appropriate category for the setting, then add a new property
     * with all of the decorations filled out. Then add a line to the Get... and Save... methods to keep
     * the items in sync. 
     * 
     * If the property being added is one that gets used by the ReportingEngine, you will also need to add
     * the code to update that property's value in the UpdateTheReportingEngineConfigValues() method.
     * -------------------------------------------------------------------------------------------------*/

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private void InitializeTheApp()
        {
            try
            { 
                re = new TSL_ReportingEngine(Properties.Settings.Default.sqlConn);
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

            UpdateTheReportingEngineConfigValues();
            UpdateTextEditorToolbarVisibility();
            if (Properties.Settings.Default.ShowHelpFileAtStartup)
            {
                LoadHelpFile("HelpFiles\\00_Getting Started.rtf", ".rtf");
                tabHelpFileTopics.IsSelected = true;
            }
            if (!Properties.Settings.Default.ApplicationHasBeenConfigured)
            {
                // Display the dialog box and wait to see if we should bail out
                AppConfigConfirmation _dlg = new AppConfigConfirmation();
                _dlg.sqlConn = Properties.Settings.Default.sqlConn;
                _dlg.ShowDialog();
                if (!_dlg.userClickedOK)
                {
                    return;
                }
                settings.ApplicationHasBeenConfigured = _dlg.doNotShowAgain;
                SaveAppSettings();
            }
            if(!CheckConnectivityAndDBVersion(false))
                UpdateDbAndCoreInfoTables(false);
            GetExtendedSettings();
        }

        private async void UpdateDbAndCoreInfoTables(bool loadRunList)
        {
            System.Windows.Input.Cursor _cursor = this.Cursor;

            tsslMessage.Content = "Updating the Core Info Table asynchronously.....";
            await re.UpdateTheCoreInfoTablesAsync();
            tsslMessage.Content = "Completed the update";
            if (loadRunList)
                PopulateDataGridWithRuns();

            btnGetRuns.IsEnabled = true;
            btnGenerateFiltered.IsEnabled = true;
            this.Cursor = _cursor;
        }

        private bool CheckConnectivityAndDBVersion(bool loadRunList)
        {
            bool sqlExceptionThrown = false;
            System.Windows.Input.Cursor _cursor = this.Cursor;
            this.Cursor = Cursors.Wait;
            tsslMessage.Content = "Checking Database Version...";
            try
            {
                if (!re.GetReportingEngineVersion(Properties.Settings.Default.CurrentVersion))
                {
                    //NOTE: Need to add message box and/or way of confirning that update needs to occur
                    string resultsFromUpdate;
                    TimeSpan ts = re.UpdateReportingEngine(out resultsFromUpdate);
                    TextRange text = new TextRange(rtbResults.Document.ContentStart, rtbResults.Document.ContentEnd);
                    text.Text = resultsFromUpdate;
                }
                sqlExceptionThrown = false;
            }
            catch (SqlException ex)
            {
                //"Cannot open database"
                //"Login failed"
                //"A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)"

                System.Windows.MessageBox.Show(ex.ToString());
                string sSqlMessage = String.Format("The application could not connect to the SQL database. Either the SQL instance is not reachable, or the " +
                    "connection string is invalid. The current connection string is:\r\n\r\n{0}\r\n\r\n Please update it on the Configuration tab by " +
                    "changing the string, move to a differnt field to commit the change, and then Save the Config update using the Options tab > Save " +
                    "Options button.", Properties.Settings.Default.sqlConn);
                System.Windows.MessageBox.Show(sSqlMessage);

                // Navigate to the Configuration right-panel tab so that the user can make database connection string changes.
                tabConfiguration.IsSelected = true;

                // Navigate to the Options tab so that the user can save database connection string changes.
                RibbonTabOptions.IsSelected = true;

                // Set the focus to the SQL Connection string.
                ApplicationSettingsPropertyGrid.Focus();

                // I wanted to use the Search box to bring the SQL Connection string property to the top OR make it the selected property but wasn't able to.
                //((VSLT_Reporting.AppConfiguration)(ApplicationSettingsPropertyGrid.SelectedObject)).sqlConn;
                sqlExceptionThrown = true;
            }
            finally
            {
                this.Cursor = _cursor;
                tsslMessage.Content = "Database Version check is complete....";
            }
            return sqlExceptionThrown;
        }


        private void ConfigureAppSettings()
        {
            if (tabConfiguration.Visibility == System.Windows.Visibility.Hidden)
            {
                tabConfiguration.Visibility = System.Windows.Visibility.Visible;
                tabConfiguration.IsSelected = true;
                btnOptionsSave.IsEnabled = true;
            }
            RibbonTabOptions.IsSelected = true;
        }

        private void SaveAppSettings()
        {
            Properties.Settings.Default.ApplicationHasBeenConfigured = true;
            settings.SaveConfigValues();

            if (re == null)
            {
                InitializeTheApp();
                return;
            }
            UpdateTheReportingEngineConfigValues();
            SetTabAvailability(true);
            UpdateTextEditorToolbarVisibility();
            RibbonTabHome.IsSelected = true;
            tabRichTextBox.IsSelected = true;
        }

        private void LoadAppSettings()
        {
            // Create a new instance of the Application settings. Load the app.config values
            // into that object. Then set the app config PropertyGrid binding to the active
            // instance. This allows us to have full access to all of the app.config settings 
            // and their category info within the PropertyGrid
            settings = new AppConfiguration();
            settings.GetConfigValues();
            ApplicationSettingsPropertyGrid.SelectedObject = settings;
            tsslEngineVersion.Content = String.Format(Msg_REPORTINGENGINEVERSION, settings.CurrentVersion);
            
            // Since I use String.Replace, if the name does not use the directive, the string will be unmodified, so no need to check the existence of the directive("<My Documents>")
            Properties.Settings.Default.FolderToStoreResults = Properties.Settings.Default.FolderToStoreResults.Replace("<My Documents>", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
            Properties.Settings.Default.ChartTemplateLocation = Properties.Settings.Default.ChartTemplateLocation.Replace("<My Documents>", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));

            // Check to see if the Reporting Folder exists. If not, create it
            if (!Directory.Exists(Properties.Settings.Default.FolderToStoreResults))
            {
                Directory.CreateDirectory(Properties.Settings.Default.FolderToStoreResults);
                Directory.CreateDirectory(Properties.Settings.Default.ChartTemplateLocation);
                tsslMessage.Content = String.Format(Msg_CREATEDRESULTSDIRECTORY, Properties.Settings.Default.FolderToStoreResults);
            }
         
        }

        private void ResetAppSettings()
        {
            Properties.Settings.Default.Reset();
            settings.GetConfigValues();
            if(re != null)
                UpdateTheReportingEngineConfigValues();
        }

        private void UpdateTheReportingEngineConfigValues()
        {
            tts = new TalkToSql(
                Properties.Settings.Default.sqlConn,
                Properties.Settings.Default.ConnectionTimeout,
                Properties.Settings.Default.CommandTimeout);

            re.sqlConn = Properties.Settings.Default.sqlConn;
            re.connTimeout = Properties.Settings.Default.ConnectionTimeout;
            re.cmdTimeout = Properties.Settings.Default.CommandTimeout;
            re.minimumPointsForConstantInterval = Properties.Settings.Default.minimumPointsForConstantInterval;
            re.minimumSecondsForConstantInterval = Properties.Settings.Default.minimumSecondsForConstantInterval;
            re.IgnoreUserNameFromAnalysisNotes = Properties.Settings.Default.IgnoreUserNameFromAnalysisNotes;
            re.SqlScriptLocation = Properties.Settings.Default.SqlScriptLocation;
            re.LoadTestDatabaseName = Properties.Settings.Default.LoadTestDatabaseName;
        }

        private void GetExtendedSettings()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(Properties.Settings.Default.ExtendedSettingsFileName);
                #region -- RibbonBar Items -----------------------------------------------------------
                foreach (XmlNode xNode in xDoc.GetElementsByTagName("RibbonBarItemDefaultValue"))
                {
                    switch (xNode.Attributes["Name"].Value)
                    {
                        case "cbNameFilterSelectedValue":
                            cbNameFilterSelectedValue.SelectedValue = xNode.InnerText;
                            break;

                        case "cbComparisonAdjectiveSelectedValue":
                            cbComparisonAdjectiveSelectedValue.SelectedValue = xNode.InnerText;
                            break;

                        case "tbComparisonPhrase":
                            tbComparisonPhrase.Text = xNode.InnerText;
                            break;

                        case "tbTableFilterString":
                            tbTableFilterString.Text = xNode.InnerText;
                            break;

                        case "intervalColumnSelectedValue":
                            cbNameFilterSelectedValue.SelectedValue = xNode.InnerText;
                            break;

                        case "tbIntervalValue":
                            tbIntervalValue.Text = xNode.InnerText;
                            break;
                    }
                }
                #endregion

                #region -- ScoreCard Settings ------------------------------------------------------------
                /*<ScoreCardItem 
                 * Name="LoadTestRunId" 
                 * DataType="int" 
                 * UseInReport="True" 
                 * ShowGraph="false" 
                 * ShowGoal="false" 
                 * Goal="1" 
                 * HigherIsBetter="true" 
                 * YAxisMax="" 
                 * Title="Load Test Run Id" 
                 * Description="The run ID of the test"></ScoreCardItem> */
                
                scoreCardFields.Clear();
                foreach (XmlNode xNode in xDoc.GetElementsByTagName("ScoreCardItem"))
                {
                    ScoreCardItem item = new ScoreCardItem();
                    item.Name = xNode.Attributes["Name"].Value;
                    item.DataType = xNode.Attributes["DataType"].Value;
                    item.UseInReport = xNode.Attributes["UseInReport"].Value.ToLower() == "true" ? true : false;
                    item.ShowGraph = xNode.Attributes["ShowGraph"].Value.ToLower() == "true" ? true : false;
                    item.ShowGoal = xNode.Attributes["ShowGoal"].Value.ToLower() == "true" ? true : false;
                    item.Goal = xNode.Attributes["Goal"].Value != "" ? Convert.ToDouble(xNode.Attributes["Goal"].Value) : 0;
                    item.HigherIsBetter = xNode.Attributes["HigherIsBetter"].Value.ToLower() == "true" ? true : false;
                    item.YAxisMax = xNode.Attributes["YAxisMax"].Value != "" ? Convert.ToInt32(xNode.Attributes["YAxisMax"].Value) : 0;
                    item.Title = xNode.Attributes["Title"].Value;
                    item.Description = xNode.Attributes["Description"].Value;
                    scoreCardFields.Add(item);
                }
                #endregion
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void SaveExtendedSettings()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                xDoc.Load(Properties.Settings.Default.ExtendedSettingsFileName);
                foreach (XmlNode xNode in xDoc.GetElementsByTagName("RibbonBarItemDefaultValue"))
                {
                    switch (xNode.Attributes["Name"].Value)
                    {
                        case "cbNameFilterSelectedValue":
                            xNode.InnerText = cbNameFilterSelectedValue.SelectedValue.ToString();
                            break;

                        case "cbComparisonAdjectiveSelectedValue":
                            xNode.InnerText = cbComparisonAdjectiveSelectedValue.SelectedValue.ToString();
                            break;

                        case "tbComparisonPhrase":
                            xNode.InnerText = tbComparisonPhrase.Text;
                            break;

                        case "tbTableFilterString":
                            xNode.InnerText = tbTableFilterString.Text;
                            break;

                        case "intervalColumnSelectedValue":
                            xNode.InnerText = cbNameFilterSelectedValue.SelectedValue.ToString();
                            break;

                        case "tbIntervalValue":
                            xNode.InnerText = tbIntervalValue.Text;
                            break;
                    }
                }
                xDoc.Save(Properties.Settings.Default.ExtendedSettingsFileName);
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
    

    /// <summary>
    /// This class duplicates all of the values that are kept in the app.config file, but adds to them different categorizations for the values that can
    /// be used by the application's PropertyGrid control to allow for easier user configuration. The property grid will bind to the active instance of
    /// this class to display and modify all the user settings. The two main methods <see cref="GetConfigValues"/> and <see cref="SaveConfigValues"/> are
    /// used to keep the two objects in sync.
    /// </summary>
    [Serializable]
    public class AppConfiguration
    {
        public AppConfiguration() { }

        #region -- Core Settings --------------------------------------------------------------------------------------------
        [System.ComponentModel.DisplayName("Current Version")]
        [System.ComponentModel.Description("The version of the application installed on this machine. It is used to verify that the correct version of code is also on the SQL database holding the results")]
        [System.ComponentModel.Category("Core Settings")]
        [System.ComponentModel.DefaultValue("5.1.0 Beta")]
        public string CurrentVersion { get; set; }

        [System.ComponentModel.DisplayName("Application Has Been Configured")]
        [System.ComponentModel.Description("Indicates that initial configuration has occurred and that the Configuration Dialog box does not need to be shown")]
        [System.ComponentModel.Category("Core Settings")]
        [System.ComponentModel.DefaultValue(false)]
        public bool ApplicationHasBeenConfigured { get; set; }

        [System.ComponentModel.DisplayName("Folder To Store Results")]
        [System.ComponentModel.Description("The folder where test and report results will get saved. NOTE: Use '<MyDocuments>' at the beginning if you want the path to be relative to the built in My Documents folder")]
        [System.ComponentModel.Category("Core Settings")]
        [System.ComponentModel.DefaultValue("<MyDocuments>\\Load Test Reports")]
        public string FolderToStoreResults { get; set; }

        [System.ComponentModel.DisplayName("Sql Script Location")]
        [System.ComponentModel.Description("The location for the SQL Scripts used to update the Load Test Database")]
        [System.ComponentModel.Category("Core Settings")]
        [System.ComponentModel.DefaultValue("\\SqlScripts\\")]
        public string SqlScriptLocation { get; set; }

        [System.ComponentModel.DisplayName("Show TextBox Editor Toolbar")]
        [System.ComponentModel.Description("Display the editor bar for the main report rich text box?")]
        [System.ComponentModel.Category("Core Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool ShowTextBoxEditorToolbar { get; set; }

        
        [System.ComponentModel.DisplayName("Show Help File At Startup")]
        [System.ComponentModel.Description("If true, the help file is displayed when the application starts")]
        [System.ComponentModel.DefaultValue(true)]
        public bool ShowHelpFileAtStartup { get; set; }
        
        #endregion

        #region -- Database Settings ----------------------------------------------------------------------------------------
        [System.ComponentModel.DisplayName("SQL Connection String")]
        [System.ComponentModel.Description("The string used to connect to the LoadTest SQL Server database")]
        [System.ComponentModel.Category("Database Settings")]
        [System.ComponentModel.DefaultValue("Data Source=.\\;Integrated Security=SSPI;Initial Catalog=LoadTest2010")]
        public string sqlConn { get; set; }

        [System.ComponentModel.DisplayName("Connection Timeout")]
        [System.ComponentModel.Description("The timeout value (in seconds) for attempting to establish a SQL Connection")]
        [System.ComponentModel.Category("Database Settings")]
        [System.ComponentModel.DefaultValue(60)]
        public int ConnectionTimeout { get; set; }

        [System.ComponentModel.DisplayName("Command Timeout")]
        [System.ComponentModel.Description("The timeout value (in seconds) for attempting to complete a SQL command")]
        [System.ComponentModel.Category("Database Settings")]
        [System.ComponentModel.DefaultValue(300)]
        public int CommandTimeout { get; set; }

        [System.ComponentModel.DisplayName("LoadTest Database Name")]
        [System.ComponentModel.Description("The name of the LoadTest database. By default, Visual Studio builds the database as 'LoadTest2010'")]
        [System.ComponentModel.Category("Database Settings")]
        [System.ComponentModel.DefaultValue("Loadtest2010")]
        public string LoadTestDatabaseName { get; set; }
        #endregion

        #region -- Chart Settings -------------------------------------------------------------------------------------------
        [System.ComponentModel.DisplayName("Chart Template Location")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Chart Settings")]
        [System.ComponentModel.DefaultValue("<MyDocuments>\\Load Test Reports\\Chart Templates\\")]
        public string ChartTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Chart Template Name")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Chart Settings")]
        [System.ComponentModel.DefaultValue("ChartTemplate.xml")]
        public string ChartTemplateName { get; set; }

        [System.ComponentModel.DisplayName("Max Machines To Chart")]
        [System.ComponentModel.Description("The maximum number of machines to buikd into a chart without prompting for user interaction")]
        [System.ComponentModel.Category("Chart Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public int maxMachinesToChartWithoutPrompting { get; set; }

        [System.ComponentModel.DisplayName("Chart Object Location")]
        [System.ComponentModel.Description("The XML file that contains the default list of charting objects to use")]
        [System.ComponentModel.Category("Chart Settings")]
        [System.ComponentModel.DefaultValue("DefaultChartingObjects.xml")]
        public string ChartObjectFileName { get; set; }

        [System.ComponentModel.DisplayName("Extended Settings Location")]
        [System.ComponentModel.Description("The XML file that contains the extended list of chart settings to use")]
        [System.ComponentModel.Category("Extended Settings")]
        [System.ComponentModel.DefaultValue("ExtendedSettings.xml")]
        public string ExtendedSettingsFileName { get; set; }

        [System.ComponentModel.DisplayName("Charting: Machine Alias Set To Use")]
        [System.ComponentModel.Description("The name of the machine list to use for populating the various charts in the reports. The actual list values must be edited directly in the 'DefaultChartingObjects.xml' file.")]
        [System.ComponentModel.DefaultValue("DefaultAliasSet")]
        [System.ComponentModel.Category("Chart Settings")]
        public string Charting_MachineAliasSetToUse { get; set; }

        [System.ComponentModel.DisplayName("Charting: Legend Row Height")]
        [System.ComponentModel.Description("The height, in pixels, that a row in the chart legend will use. This allows the vertical height of the chart to properly scale for the loegend entries")]
        [System.ComponentModel.DefaultValue(48)]
        [System.ComponentModel.Category("Chart Settings")]
        public int Charting_LegendRowHeight { get; set; }
        #endregion

        #region -- Template Settings ----------------------------------------------------------------------------------------
        //[System.ComponentModel.DisplayName("Report Template Location")]
        //[System.ComponentModel.Description("")]
        //[System.ComponentModel.Category("Template Settings")]
        //[System.ComponentModel.DefaultValue("\\Templates\\00_ReportTemplate_Simple.docx")]
        //public string TemplateLocation { get; set; }

        //[System.ComponentModel.DisplayName("Top Ten Template Location")]
        //[System.ComponentModel.Description("")]
        //[System.ComponentModel.Category("Template Settings")]
        //[System.ComponentModel.DefaultValue("\\Templates\\01_TopXXTemplate.docx")]
        //public string TopTenTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Scenario Template Location")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("\\Templates\\01_ScenarioTemplate.docx")]
        public string ScenarioTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("LoadTest Properties Template Loacation")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("\\Templates\\01_LoadTestPropertiesTemplate.docx")]
        public string LoadTestPropertiesTemplateLoacation { get; set; }

        //[System.ComponentModel.DisplayName("Appendix Template Location")]
        //[System.ComponentModel.Description("")]
        //[System.ComponentModel.Category("Template Settings")]
        //[System.ComponentModel.DefaultValue("\\Templates\\01_AppendixTemplate.docx")]
        //public string AppendixTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Database Inforamtion Template Location")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("Templates\\DatabaseInfoTemplate.xaml")]
        public string DatabaseInfoTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Database File Inforamtion Template Location")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("Templates\\DatabaseFileInfoLineTemplate.xaml")]
        public string DatabaseFileInfoLineTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Database Top Tables Template Location")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("Templates\\DatabaseInfoTopTablesTemplate.xaml")]
        public string DatabaseInfoTopTablesTemplateLocation { get; set; }

        [System.ComponentModel.DisplayName("Chart Template With Legend Name")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Template Settings")]
        [System.ComponentModel.DefaultValue("Templates\\ChartTemplateWithLegend.xml")]
        public string ChartTemplateWithLegendName { get; set; }
        #endregion

        #region -- Report Settings ------------------------------------------------------------------------------------------
        [System.ComponentModel.DisplayName("Default Report Name")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue("Run XXX TestReport.docx")]
        public string DefaultReportName { get; set; }

        [System.ComponentModel.DisplayName("Number Top Slowest")]
        [System.ComponentModel.Description("The number of rows to report the top slowest tests, transactions, pages, etc.")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(10)]
        public int numTopSlowest { get; set; }

        [System.ComponentModel.DisplayName("Include Scenarios In Report")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool includeScenariosInReport { get; set; }

        [System.ComponentModel.DisplayName("Include Appendix In Report")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool includeAppendixInReport { get; set; }

        [System.ComponentModel.DisplayName("Include Charts In Report")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool includeChartsInReport { get; set; }

        [System.ComponentModel.DisplayName("Include Test Rig Machines in Utilization Charts")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(false)]
        public bool includeRigMachinesInUtilizationCharts { get; set; }

        [System.ComponentModel.DisplayName("Include Debug Timing Info In Report")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool includeDebugTimingInfoInReport { get; set; }

        [System.ComponentModel.DisplayName("Use Detailed Timings For Report When Available")]
        [System.ComponentModel.Description("If true, the report timings shown for Test, Transaction and Page will be recalculated using the detailed timing info. Otherwise, all timing charts and tables will be built using the summary data stored in the DB")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool UseDetailedTimingsForReportWhenAvailable { get; set; }

        [System.ComponentModel.DisplayName("Include 'GroupedByName' Timings Tables In Report")]
        [System.ComponentModel.Description("Build summary tables of the timings for pages and transactions that are grouped by name. This allows a single summary for each page or transaction name that is calculated by all values for the timer across all tests and scenarios")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool include_GROUPEDBYNAME_TimingsTablesInReport { get; set; }

        [System.ComponentModel.DisplayName("Order 'GroupedByName' Timings Tables by Avg Time")]
        [System.ComponentModel.Description("Orders the tables based on Avg Time (slowest to Fastest) if True, or by the Name if False")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool order_GROUPEDBYNAME_Timings_ByAvgTime { get; set; }

        [System.ComponentModel.DisplayName("Add Interval Timings To Report When Available")]
        [System.ComponentModel.Description("If true, then the default report will include interval timing tables whenever intervals are available in the run.")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool addIntervalTimingsToReportWhenAvailable { get; set; }

        [System.ComponentModel.DisplayName("include Test Times For Interval Reporting")]
        [System.ComponentModel.Description("If true, then the default report will include TEST interval timing tables whenever intervals are available in the run.")]
        [System.ComponentModel.Category("Report Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool includeTestTimesForIntervalReporting { get; set; }
        #endregion

        #region -- Analysis Settings ----------------------------------------------------------------------------------------
        [System.ComponentModel.DisplayName("Minimum Points For Constant Interval")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Analysis Settings")]
        [System.ComponentModel.DefaultValue(10)]
        public int minimumPointsForConstantInterval { get; set; }

        [System.ComponentModel.DisplayName("Minimum Seconds For Constant Interval")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Analysis Settings")]
        [System.ComponentModel.DefaultValue(60)]
        public int minimumSecondsForConstantInterval { get; set; }

        [System.ComponentModel.DisplayName("Ignore User Name From Analysis Notes")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.Category("Analysis Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool IgnoreUserNameFromAnalysisNotes { get; set; }

        [System.ComponentModel.DisplayName("Use Detailed Timings For Tables When Available")]
        [System.ComponentModel.Description("If true, this setting enables the ability to choose whether to recalculate timing information based on pass/fail and warmup/cooldown, etc. NOTE: This will only work if the selected test run contains detailed timing information.")]
        [System.ComponentModel.Category("Analysis Settings")]
        [System.ComponentModel.DefaultValue(true)]
        public bool UseDetailedTimingsForTablesWhenAvailable { get; set; }
        #endregion

        /// <summary>
        /// Used to load the app.config user settings into the  <see cref="AppConfiguration"/> class settings
        /// </summary>
        public void GetConfigValues()
        {
            Properties.Settings.Default.Reload();
            this.ApplicationHasBeenConfigured = Properties.Settings.Default.ApplicationHasBeenConfigured;
            this.ChartTemplateLocation = Properties.Settings.Default.ChartTemplateLocation;
            this.ChartTemplateName = Properties.Settings.Default.ChartTemplateName;
            this.CommandTimeout = Properties.Settings.Default.CommandTimeout;
            this.ConnectionTimeout = Properties.Settings.Default.ConnectionTimeout;
            this.CurrentVersion = Properties.Settings.Default.CurrentVersion;
            this.DefaultReportName = Properties.Settings.Default.DefaultReportName;
            this.FolderToStoreResults = GetFolderToStoreResultsLocation(true);
            this.includeAppendixInReport = Properties.Settings.Default.includeAppendixInReport;
            this.includeChartsInReport = Properties.Settings.Default.includeChartsInReport;
            this.includeDebugTimingInfoInReport = Properties.Settings.Default.includeDebugTimingInfoInReport;
            this.includeScenariosInReport = Properties.Settings.Default.includeScenariosInReport;
            this.LoadTestDatabaseName = Properties.Settings.Default.LoadTestDatabaseName;
            this.LoadTestPropertiesTemplateLoacation = Properties.Settings.Default.LoadTestPropertiesTemplateLocation;
            this.maxMachinesToChartWithoutPrompting = Properties.Settings.Default.maxMachinesToChartWithoutPrompting;
            this.minimumPointsForConstantInterval = Properties.Settings.Default.minimumPointsForConstantInterval;
            this.minimumSecondsForConstantInterval = Properties.Settings.Default.minimumSecondsForConstantInterval;
            this.numTopSlowest = Properties.Settings.Default.numTopSlowest;
            this.IgnoreUserNameFromAnalysisNotes = Properties.Settings.Default.IgnoreUserNameFromAnalysisNotes;
            this.ScenarioTemplateLocation = Properties.Settings.Default.ScenarioTemplateLocation;
            this.sqlConn = Properties.Settings.Default.sqlConn;
            this.SqlScriptLocation = Properties.Settings.Default.SqlScriptLocation;
            this.DatabaseInfoTemplateLocation = Properties.Settings.Default.DatabaseInfoTemplateLocation;
            this.DatabaseFileInfoLineTemplateLocation = Properties.Settings.Default.DatabaseFileInfoLineTemplateLocation;
            this.DatabaseInfoTopTablesTemplateLocation = Properties.Settings.Default.DatabaseInfoTopTablesTemplateLocation;
            this.ChartObjectFileName = Properties.Settings.Default.ChartObjectFileName;
            this.ExtendedSettingsFileName = Properties.Settings.Default.ExtendedSettingsFileName;
            this.includeRigMachinesInUtilizationCharts = Properties.Settings.Default.includeRigMachinesInUtilizationCharts;
            this.UseDetailedTimingsForReportWhenAvailable = Properties.Settings.Default.UseDetailedTimingsForReportWhenAvailable;
            this.ShowTextBoxEditorToolbar = Properties.Settings.Default.ShowTextBoxEditorToolbar;
            this.ChartTemplateWithLegendName = Properties.Settings.Default.ChartTemplateWithLegendName;
            this.ShowHelpFileAtStartup = Properties.Settings.Default.ShowHelpFileAtStartup;
            this.UseDetailedTimingsForTablesWhenAvailable = Properties.Settings.Default.UseDetailedTimingsForTablesWhenAvailable;
            this.include_GROUPEDBYNAME_TimingsTablesInReport = Properties.Settings.Default.Include_GROUPEDBYNAME_TimingsTablesInReport;
            this.order_GROUPEDBYNAME_Timings_ByAvgTime = Properties.Settings.Default.Order_GROUPEDBYNAME_Timings_ByAvgTime;
            this.Charting_MachineAliasSetToUse = Properties.Settings.Default.Charting_MachineAliasSetToUse;
            this.Charting_LegendRowHeight = Properties.Settings.Default.Charting_LegendRowHeight;
            this.addIntervalTimingsToReportWhenAvailable = Properties.Settings.Default.AddIntervalTimingsToReportWhenAvailable;
            this.includeTestTimesForIntervalReporting = Properties.Settings.Default.includeTestTimesForIntervalReporting;

        }

        /// <summary>
        /// Used to set the <see cref="AppConfiguration"/> class settings back into the app.config user settings and then to save them.
        /// </summary>
        public void SaveConfigValues()
        {
            Properties.Settings.Default.ApplicationHasBeenConfigured = this.ApplicationHasBeenConfigured;
            Properties.Settings.Default.UseDetailedTimingsForReportWhenAvailable = this.UseDetailedTimingsForReportWhenAvailable;
            Properties.Settings.Default.includeRigMachinesInUtilizationCharts = this.includeRigMachinesInUtilizationCharts;
            Properties.Settings.Default.ChartObjectFileName = this.ChartObjectFileName;
            Properties.Settings.Default.ExtendedSettingsFileName = this.ExtendedSettingsFileName;
            Properties.Settings.Default.DatabaseInfoTopTablesTemplateLocation = this.DatabaseInfoTopTablesTemplateLocation;
            Properties.Settings.Default.DatabaseFileInfoLineTemplateLocation = this.DatabaseFileInfoLineTemplateLocation;
            Properties.Settings.Default.DatabaseInfoTemplateLocation = this.DatabaseInfoTemplateLocation;
            Properties.Settings.Default.SqlScriptLocation = this.SqlScriptLocation;
            Properties.Settings.Default.sqlConn = this.sqlConn;
            Properties.Settings.Default.ScenarioTemplateLocation = this.ScenarioTemplateLocation;
            Properties.Settings.Default.IgnoreUserNameFromAnalysisNotes = this.IgnoreUserNameFromAnalysisNotes;
            Properties.Settings.Default.numTopSlowest = this.numTopSlowest;
            Properties.Settings.Default.minimumSecondsForConstantInterval = this.minimumSecondsForConstantInterval;
            Properties.Settings.Default.minimumPointsForConstantInterval = this.minimumPointsForConstantInterval;
            Properties.Settings.Default.maxMachinesToChartWithoutPrompting = this.maxMachinesToChartWithoutPrompting;
            Properties.Settings.Default.LoadTestPropertiesTemplateLocation = this.LoadTestPropertiesTemplateLoacation;
            Properties.Settings.Default.LoadTestDatabaseName = this.LoadTestDatabaseName;
            Properties.Settings.Default.includeScenariosInReport = this.includeScenariosInReport;
            Properties.Settings.Default.includeDebugTimingInfoInReport = this.includeDebugTimingInfoInReport;
            Properties.Settings.Default.includeChartsInReport = this.includeChartsInReport;
            Properties.Settings.Default.includeAppendixInReport = this.includeAppendixInReport;
            Properties.Settings.Default.FolderToStoreResults = this.FolderToStoreResults;
            Properties.Settings.Default.DefaultReportName = this.DefaultReportName;
            Properties.Settings.Default.CurrentVersion = this.CurrentVersion;
            Properties.Settings.Default.ConnectionTimeout = this.ConnectionTimeout;
            Properties.Settings.Default.CommandTimeout = this.CommandTimeout;
            Properties.Settings.Default.ChartTemplateName = this.ChartTemplateName;
            Properties.Settings.Default.ChartTemplateLocation = this.ChartTemplateLocation;
            Properties.Settings.Default.ShowTextBoxEditorToolbar = this.ShowTextBoxEditorToolbar;
            Properties.Settings.Default.ChartTemplateWithLegendName = this.ChartTemplateWithLegendName;
            Properties.Settings.Default.ShowHelpFileAtStartup = this.ShowHelpFileAtStartup;
            Properties.Settings.Default.UseDetailedTimingsForTablesWhenAvailable = this.UseDetailedTimingsForTablesWhenAvailable;
            Properties.Settings.Default.Include_GROUPEDBYNAME_TimingsTablesInReport = this.include_GROUPEDBYNAME_TimingsTablesInReport;
            Properties.Settings.Default.Order_GROUPEDBYNAME_Timings_ByAvgTime = this.order_GROUPEDBYNAME_Timings_ByAvgTime;
            Properties.Settings.Default.Charting_MachineAliasSetToUse = this.Charting_MachineAliasSetToUse;
            Properties.Settings.Default.Charting_LegendRowHeight = this.Charting_LegendRowHeight;
            Properties.Settings.Default.AddIntervalTimingsToReportWhenAvailable = this.addIntervalTimingsToReportWhenAvailable;
            Properties.Settings.Default.includeTestTimesForIntervalReporting = this.includeTestTimesForIntervalReporting;
            Properties.Settings.Default.Save();
        }

        /// <summary>
        /// Checks the Setting for the location to store results and determines if it should use the relative 'My Documents' path
        /// </summary>
        /// <param name="replaceTheFolderPathInTheProperties">If true, the method will replace the relative path in the Properties.Settings.Default property with the absolute path</param>
        /// <returns></returns>
        public string GetFolderToStoreResultsLocation(bool replaceTheFolderPathInTheProperties)
        {
            string folderLocation = Properties.Settings.Default.FolderToStoreResults;
            if(folderLocation.StartsWith("<MyDocuments>"))
            {
                folderLocation = folderLocation.Replace("<MyDocuments>", Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
                if(replaceTheFolderPathInTheProperties)
                    Properties.Settings.Default.FolderToStoreResults = folderLocation;
            }
            return folderLocation;
        }
    }

    public class ScoreCardItem
    {
        /*<ScoreCardItem 
         * Name="LoadTestRunId" 
         * DataType="int" 
         * UseInReport="True" 
         * ShowGraph="false" 
         * ShowGoal="false" 
         * Goal="1" 
         * HigherIsBetter="true" 
         * YAxisMax="" 
         * Title="Load Test Run Id" 
         * Description="The run ID of the test"></ScoreCardItem> */

        public string Name { get; set; }
        public string DataType { get; set; }
        public bool UseInReport { get; set; }
        public bool ShowGraph { get; set; }
        public bool ShowGoal { get; set; }
        public double Goal { get; set; }
        public bool HigherIsBetter { get; set; }
        public int YAxisMax { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
    }

    public enum ConfigReturnValues
    {
        UserClicked_OK = 1,

        UserClicked_Cancel = 2,

        SqlException = 3
    };
}



